from rest_framework import serializers
from booktest.models import BookInfo

"""
一,定义序列化器
1, 定义类,继承自Serializer
2, 字段名,和模型类的名字一样
3, 字段类型, 和模型类的字段类型一样
4, 字段选项, 和模型类的选项一样
    label: 序列化器字段说明
    read_only: 只读

二,使用序列化成
1,序列化:模型类对象,转成json(dict)

2,反序列化:
A.校验
    a,数据类型的校验
    b,选项校验
    c,单字段校验,方法
    d,多字段校验,方法
    e,自定义校验,方法

B,入库

"""


# 1.定义书籍序列化器
class BookInfoSerializer(serializers.Serializer):
    id = serializers.IntegerField(label="id", read_only=True)
    btitle = serializers.CharField(max_length=20, label="名称")
    bpub_date = serializers.DateField(label="发布日期")
    bread = serializers.IntegerField(default=0, label="阅读量")
    bcomment = serializers.IntegerField(default=0, label="评论量")
    is_delete = serializers.BooleanField(default=False, label="逻辑删除")

    # 1.主键形式many=True,表示一本书籍里面可以包含多个影响
    # heroinfo_set = serializers.PrimaryKeyRelatedField(read_only=True,many=True)

    # 2.__str__返回值,作为结果
    # heroinfo_set = serializers.StringRelatedField(read_only=True, many=True)

    # 3.单字段校验,方法,对书籍名进行校验;value就是需要校验的字段
    def validate_btitle(self, value):
        # 1.判断内容,校验不通过一定要抛出异常
        if '金瓶'not in value:
            raise serializers.ValidationError("书籍名不包含金瓶")
        # 2.校验通过,返回value即可
        return value

    # 4.多字段校验,方法,对评价量和阅读量进行校验,传入进来的字典
    def validate(self, attrs):
        # 1.获取阅读量,评价量
        bread = attrs["bread"]
        bcomment = attrs["bcomment"]
        # 2.判断
        if bcomment > bread:
            raise serializers.ValidationError("评论量大于了阅读量")
        # 3.返回
        return attrs

    # 5.重写create方法,入库数据
    def create(self, validated_data):
        print(validated_data)
        """
        :param validated_data: 校验成功之后的数据
        :return:
        """
        # 1.创建书籍对象,入库
        book = BookInfo.objects.create(**validated_data)

        # 2.返回
        return book

    # 6.重写update方法,更新数据
    def update(self, instance, validated_data):
        """
        :param instance: 表示要更新的对象
        :param validated_data: 更新的数据
        :return:
        """
        # 1.更新数据
        instance.btitle = validated_data["btitle"]
        instance.bpub_date = validated_data["bpub_date"]
        instance.bread = validated_data["bread"]
        instance.bcomment = validated_data["bcomment"]
        instance.save()

        # BookInfo.objects.filter(id=instance.id).update(**validated_data)

        # 2.返回
        return instance



# 2.定义英雄序列化器
class HeroInfoSerializer(serializers.Serializer):
    """英雄数据序列化器"""
    GENDER_CHOICES = (
        (0, 'female'),
        (1, 'male')
    )
    id = serializers.IntegerField(label='ID', read_only=True)
    hname = serializers.CharField(label='名字', max_length=20)
    hgender = serializers.ChoiceField(choices=GENDER_CHOICES, label='性别',required=False)
    hcomment = serializers.CharField(label='描述信息', max_length=200, required=False)

    # 1.主键, 转换关联的外键, 需要提供,read_only=True, 或者是 queryset=BookInfo.objects.all()
    # 输出的时候,以主键的形式表示
    # hbook = serializers.PrimaryKeyRelatedField(read_only=True)
    # hbook = serializers.PrimaryKeyRelatedField(queryset=BookInfo.objects.all())

    # 2.__str__, 书籍模型类, str返回值作为结果
    # hbook = serializers.StringRelatedField(read_only=True)

    # 3.以书籍的序列化器, 作为结果即可
    # hbook = BookInfoSerializer(read_only=True)



# 3.定义书籍,模型类序列化器
class BookInfoModelSerializer(serializers.ModelSerializer):
    # 1.自己编写的字段
    mobile = serializers.CharField(max_length=11, label="手机号", read_only=True)

    class Meta:
        model = BookInfo
        # fields = "__all__" #基于模型类生成所有的字段
        # fields = ("id","btitle","mobile")

        # 2,除了哪些字段,其他都生成; 和fields互斥
        # exclude = ("id","btitle")


        # 3.设置只读字段(模型类中)
        # read_only_fields = ('bpub_date',"btitle","bread")

        # 4.添加额外的约束
        # extra_kwargs = {
        #
        #     "bread":{
        #         "min_value":0,
        #         "max_value":1000
        #     },
        #
        #     "is_delete":{
        #         "required":True
        #     }
        # }